package com.fas.system.service.impl;

import com.fas.common.constant.Constants;
import com.fas.common.core.domain.AjaxResult;
import com.fas.common.core.redis.RedisCache;
import com.fas.common.utils.DictUtils;
import com.fas.common.utils.StringUtils;
import com.fas.system.domain.FasEquipment;
import com.fas.system.domain.FasEquipmentAlarm;
import com.fas.system.domain.FasEquipmentStatusHistory;
import com.fas.system.domain.vo.EquipmentAlarmVo;
import com.fas.system.domain.vo.EquipmentVo;
import com.fas.system.mapper.FasEquipmentMapper;
import com.fas.system.mapper.FasEquipmentStatusHistoryMapper;
import com.fas.system.service.IFasEquipmentAlarmService;
import com.fas.system.service.IFasEquipmentService;
import com.fas.system.util.OrderldUtil;
import com.fas.system.websocket.PushData;
import com.fas.system.websocket.PushService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * 设备信息Service业务层处理
 *
 * @author ruoyi
 * @date 2022-05-05
 */
@Service
public class FasEquipmentServiceImpl implements IFasEquipmentService {

    private final static Logger logger = LoggerFactory.getLogger(FasEquipmentServiceImpl.class);

    @Resource
    private FasEquipmentMapper fasEquipmentMapper;
    @Resource
    private PushService pushService;
    @Resource
    private IFasEquipmentAlarmService fasEquipmentAlarmService;
    @Resource
    private FasEquipmentStatusHistoryMapper fasEquipmentStatusHistoryMapper;
    @Resource
    private RedisCache redisCache;


    /**
     * 查询设备信息
     *
     * @param id 设备信息主键
     * @return 设备信息
     */
    @Override
    public FasEquipment selectFasEquipmentById(Long id, Long deptId) {
        return fasEquipmentMapper.selectFasEquipmentById(id, deptId);
    }

    /**
     * 查询设备信息列表
     *
     * @param fasEquipment 设备信息
     * @return 设备信息
     */
    @Override
    public List<FasEquipment> selectFasEquipmentList(FasEquipment fasEquipment) {
        return fasEquipmentMapper.selectFasEquipmentList(fasEquipment);
    }

    /**
     * 新增设备信息
     *
     * @param fasEquipment 设备信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertFasEquipment(FasEquipment fasEquipment) {
        String id = genEquipmentNumber();
        fasEquipment.setEquipmentNumber(id);
        return fasEquipmentMapper.insertFasEquipment(fasEquipment);
    }

    /**
     * 修改设备信息
     *
     * @param fasEquipment 设备信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateFasEquipment(FasEquipment fasEquipment) {
        return fasEquipmentMapper.updateFasEquipment(fasEquipment);
    }

    /**
     * 批量删除设备信息
     *
     * @param ids 需要删除的设备信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteFasEquipmentByIds(Long[] ids) {
        return fasEquipmentMapper.deleteFasEquipmentByIds(ids);
    }

    /**
     * 删除设备信息信息
     *
     * @param id 设备信息主键
     * @return 结果
     */
    @Override
    public int deleteFasEquipmentById(Long id) {
        return fasEquipmentMapper.deleteFasEquipmentById(id);
    }

    @Override
    public List<FasEquipment> findAllEquipment(FasEquipment fasEquipment) {
        List<FasEquipment> list = fasEquipmentMapper.findAllEquipment(fasEquipment);
        list.forEach(ll -> ll.setCompanyName(FasCooperationCompanyServiceImpl.COMPANY_NAMES.get(ll.getCooperationCompanyId())));
        return list;
    }

    @Override
    public List<FasEquipment> findLikeEngineer(FasEquipment fasEquipment) {
        List<FasEquipment> list = fasEquipmentMapper.findLikeEngineer(fasEquipment);
        list.forEach(ll -> ll.setCompanyName(FasCooperationCompanyServiceImpl.COMPANY_NAMES.get(ll.getCooperationCompanyId())));
        return list;
    }

    @Override
    public List<FasEquipment> equipmentdetails(String equipmentNumber) {
        return fasEquipmentMapper.equipmentdetails(equipmentNumber);
    }

    @Override
    public List<FasEquipment> findAll(FasEquipment fasEquipment) {
        return fasEquipmentMapper.findAll(fasEquipment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateDeviceStatus(EquipmentVo equipmentVo) {

        String deviceId = equipmentVo.getDeviceId();
        Integer status = equipmentVo.getStatus();
        String remark = equipmentVo.getAdditional();
        String data = equipmentVo.getData();
        FasEquipment equipment = new FasEquipment();
        equipment.setEquipmentNumber(deviceId);
        equipment.setStatus(status);
        equipment.setRemark(remark);
        equipment.setData(data);
        int result = fasEquipmentMapper.updateByEquipmentNumber(equipment);

        //设备状态为：报警，需要巡检员查看，巡检员在报警列表中可以查看到此数据
        if (status == Constants.DEVICE_TYPE_ALARM || status == Constants.DEVICE_TYPE_FAULT ) {
            Date date = new Date();//报警时间

            //报警消息实体类
            List<EquipmentAlarmVo> equipmentAlarmVos = fasEquipmentMapper.selectHomePageById(deviceId, null);
            if (CollectionUtils.isEmpty(equipmentAlarmVos)) {
                return AjaxResult.error("该设备不存在！");
            }
            EquipmentAlarmVo equipmentAlarmVo = equipmentAlarmVos.get(0);
            // 记录报警记录
            FasEquipmentAlarm fasEquipmentAlarm = saveFasEquipmentAlarm(equipmentVo, date, equipmentAlarmVo.getId());
            // 推送设备报警消息
            Integer alarmId = fasEquipmentAlarm.getId();
            pushEquipmentAlarmMsg(equipmentAlarmVo, status, remark, date, alarmId,deviceId);

            //  // TODO 给维保单位人员发送短信
//            fasEquipmentAlarmService.syncSendMsg(alarmId);

        }

        //将设备状态数据记录在-设备状态历史表中
        FasEquipmentStatusHistory history = new FasEquipmentStatusHistory(deviceId, status, remark, data);
        fasEquipmentStatusHistoryMapper.insert(history);
        return result > 0 ? AjaxResult.success() : AjaxResult.error("设备状态更新失败，请重试");
    }

    /**
     * 将报警的设备保存至设备报警表中
     *
     * @param equipmentVo
     * @param date
     * @return
     */
    private FasEquipmentAlarm saveFasEquipmentAlarm(EquipmentVo equipmentVo, Date date, Integer deviceId) {
        FasEquipmentAlarm fasEquipmentAlarm = new FasEquipmentAlarm();
        fasEquipmentAlarm.setEquipmentId(deviceId);
        fasEquipmentAlarm.setStatus(equipmentVo.getStatus());
        fasEquipmentAlarm.setAlarmTime(date);
        fasEquipmentAlarm.setAlarmReason(equipmentVo.getAdditional());
        // 报警消息未读
        fasEquipmentAlarm.setUnread(1);
        fasEquipmentAlarmService.insertFasEquipmentAlarm(fasEquipmentAlarm);
        return fasEquipmentAlarm;
    }

    @Override
    public int read(Integer alarmId) {
        FasEquipmentAlarm equipmentAlarm = new FasEquipmentAlarm();
        equipmentAlarm.setId(alarmId);
        equipmentAlarm.setUnread(2);//消息已读
        return fasEquipmentAlarmService.updateFasEquipmentAlarm(equipmentAlarm);
    }

    /**
     * 设备的未读消息
     */
    public List<EquipmentAlarmVo> unreadList(Integer userId) {
        //报警消息实体类  unread:消息是否已读（1：未读，2：已读）
        List<EquipmentAlarmVo> list = fasEquipmentMapper.selectHomePageByUserId(null, 1,userId);
        list.forEach(ll -> ll.setCompanyName(FasCooperationCompanyServiceImpl.COMPANY_NAMES.get(ll.getCooperationCompanyId())));
        return list;
    }

    @Override
    public List<FasEquipment> miniappEquipmentList(FasEquipment fasEquipment) {
        List<FasEquipment> list = fasEquipmentMapper.miniappEquipmentList(fasEquipment);
        list.stream().filter(f -> StringUtils.isNotBlank(f.getSystemId()))
                .forEach(a -> a.setSystemName(DictUtils.getDictLabel("sys_equipment_system", a.getSystemId())));
        return list;
    }

    @Override
    public List<FasEquipmentStatusHistory> listDevicePointData(FasEquipmentStatusHistory history) {
        return fasEquipmentStatusHistoryMapper.listDevicePointData(history);
    }

    @Override
    @Transactional
    public AjaxResult importFasEquipment(List<FasEquipment> equipmentList) {
        logger.info("导入的设备信息：" + equipmentList);
        List<String> errorMsg = new ArrayList<>();
        List<FasEquipment> insertData = new ArrayList<>();
        for (FasEquipment fasEquipment : equipmentList) {
            String equipmentNumber = fasEquipment.getEquipmentNumber();
            List<EquipmentAlarmVo> equipmentAlarmVos = fasEquipmentMapper.selectHomePageById(equipmentNumber, null);
            if (equipmentAlarmVos.size() > 0) {
                errorMsg.add(equipmentNumber);
                continue;
            }
            String id = genEquipmentNumber();
            fasEquipment.setEquipmentNumber(id);
            fasEquipment.setManufacturerName(fasEquipment.getManufacturerName().trim());
            fasEquipment.setCommunicationProtocol(fasEquipment.getCommunicationProtocol().trim());
            fasEquipment.setBrand(fasEquipment.getBrand().trim());
            fasEquipment.setDeviceModel(fasEquipment.getDeviceModel().trim());
            insertData.add(fasEquipment);
        }
        if (errorMsg.size() > 0) {
            return AjaxResult.error("errorMsg", "重复的设备数据，编号为: " + StringUtils.join(errorMsg, ","));
        }
        if (insertData.size() > 0) {
            int count = fasEquipmentMapper.batchInsertEquipment(insertData);
            return count > 0 ? AjaxResult.success() : AjaxResult.error();
        }
        return AjaxResult.error("导入的数据为空");
    }

    /**
     * 发送设备报警消息
     *
     * @param equipmentAlarmVo
     * @param status
     * @param remark
     * @param date
     * @param alarmId
     */
    private void pushEquipmentAlarmMsg(EquipmentAlarmVo equipmentAlarmVo, Integer status, String remark, Date date, Integer alarmId,String deviceId) {
        equipmentAlarmVo.setStatus(status);
        equipmentAlarmVo.setAlarmReason(remark);
        equipmentAlarmVo.setAlarmTime(date);
        //报警表id，用来查看消息是否已读
        equipmentAlarmVo.setAlarmId(alarmId);
        // 如果设备状态为报警则推送数据至前端
        PushData<List<EquipmentAlarmVo>> listPushData = new PushData<>(Constants.EQUIPMENT, Collections.singletonList(equipmentAlarmVo));
        listPushData.setUserList(pushService.getManUserList(deviceId));
        pushService.sendMsg(listPushData);
    }

    private String genEquipmentNumber() {
        boolean flag = true;
        String id = "";
        while (flag) { // 生成设备编号，如果数据库中存在则继续生成
            id = OrderldUtil.getRandomStr(9);
            List<FasEquipment> list = fasEquipmentMapper.equipmentdetails(id);
            if (CollectionUtils.isEmpty(list)) {
                flag = false;
            }
        }
        return id;
    }

}
